package factory;

import java.util.HashMap;
import java.util.Map;

import loadsave.Memento;
import loadsave.loadsaveobject.Iterator;
import loadsave.loadsaveobject.LoadSaveMapComposite;
import loadsave.loadsaveobject.LoadSaveObject;
import loadsave.loadsaveobject.LoadSaveObjectComposite;
import loadsave.loadsaveobject.LoadSavePrimitive;
import map.terrain.Dirt;
import map.terrain.Grass;
import map.terrain.Lava;
import map.terrain.Marble;
import map.terrain.Mountain;
import map.terrain.Obsidian;
import map.terrain.Terrain;
import map.terrain.Water;

public class TerrainFactory implements loadsave.LoadSaveable {

    private static java.util.Map<String, Terrain> terrainMap;
    private static Map<String, Terrain> typeMap;
    
    /**
     * initialize and populate the static map
     */
    static {
    	typeMap = new HashMap<String, Terrain>();
    	Terrain toAdd = new Dirt();
    	typeMap.put(toAdd.getName(), toAdd);
    	toAdd = new Grass();
    	typeMap.put(toAdd.getName(), toAdd);
    	toAdd = new Lava();
    	typeMap.put(toAdd.getName(), toAdd);
    	toAdd = new Marble();
    	typeMap.put(toAdd.getName(), toAdd);
    	toAdd = new Mountain();
    	typeMap.put(toAdd.getName(), toAdd);
    	toAdd = new Obsidian();
    	typeMap.put(toAdd.getName(), toAdd);
    	toAdd = new Water();
    	typeMap.put(toAdd.getName(), toAdd);
        
        terrainMap = getTypeMap();
    }
    
    /**
     * getter for the map type
     * @return
     */
    protected static Map<String, Terrain> getTypeMap() {
        return typeMap;
    }
    
    /**
     * return a terrain based on the passed in string
     * @param terrainType
     * @return
     */
    public static Terrain createTerrain( String terrainType ) {
        return terrainMap.get(terrainType);
    }
    
	@Override
	public Memento getMemento() {
		return new Memento() {
			
			@Override
			public LoadSaveObject getState() {
				LoadSaveObjectComposite toReturn = new LoadSaveObjectComposite("terrainFactory", "TerrainFactory");
				LoadSaveMapComposite map = new LoadSaveMapComposite("terrainMap", "HashMap", "String", "Terrain");
				for (String s : TerrainFactory.terrainMap.keySet()) {
					map.add(new LoadSavePrimitive("", "", s), TerrainFactory.terrainMap.get(s).getMemento().getState());
				}
				toReturn.add(map.getName(), map);
				return toReturn;
			}
			
			@Override
			public void restoreState(LoadSaveObject lso) {
				TerrainFactory.terrainMap = getTypeMap();
				Iterator<LoadSaveObject> i = lso.get("terrainMap").getIterator();
				for (i.init(); i.hasNext(); i.next()) {
					TerrainFactory.terrainMap.put(i.getCurrKey().getValue(), TerrainFactory.getTypeMap().get(i.getCurrVal().getType()));
					TerrainFactory.terrainMap.get(i.getCurrKey().getValue()).getMemento().restoreState(i.getCurrVal());
				}
			}
			
		};
	}
    
}
